package com.bookmanger.server.service.impl;

import com.bookmanger.common.result.Result;
import com.bookmanger.pojo.Entity.BookType;
import com.bookmanger.pojo.VO.BookTypeTreeVO;
import com.bookmanger.server.mapper.BookTypeMapper;
import com.bookmanger.server.service.BookTypeService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
@Slf4j
public class BookTypeServiceImpl implements BookTypeService {
    
    // Redis中存储图书分类的键
    private static final String BOOK_TYPE_KEY = "book:types";
    // 过期时间（小时）
    private static final long BOOK_TYPE_EXPIRE = 24;
    
    @Autowired
    private BookTypeMapper bookTypeMapper;
    
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    
    @Autowired
    private ObjectMapper objectMapper;
    
    @Override
    public Result findAll() {
        List<BookType> bookTypes = bookTypeMapper.findAll();
        return Result.success(bookTypes);
    }
    
    @Override
    public Result syncBookTypesToRedis() {
        try {
            List<BookType> bookTypes = bookTypeMapper.findAllNotDeleted();

            List<BookType> treeBookTypes = buildBookTypeTree(bookTypes);

            BookTypeTreeVO bookTypeTreeVO = new BookTypeTreeVO();
            bookTypeTreeVO.setRootCategories(treeBookTypes);
            bookTypeTreeVO.setTotalCount(bookTypes.size());

            String bookTypesJson = objectMapper.writeValueAsString(bookTypeTreeVO);

            stringRedisTemplate.opsForValue().set(BOOK_TYPE_KEY, bookTypesJson, BOOK_TYPE_EXPIRE, TimeUnit.HOURS);
            
            log.info("成功将图书分类同步到Redis，共{}条记录", bookTypes.size());
            return getBookTypesFromRedis();
        } catch (Exception e) {
            log.error("同步图书分类到Redis时发生错误", e);
            return Result.error("同步失败: " + e.getMessage());
        }
    }
    
    @Override
    public Result getBookTypesFromRedis() {
        try {
            String bookTypesJson = stringRedisTemplate.opsForValue().get(BOOK_TYPE_KEY);
            
            if (bookTypesJson == null) {
                return Result.error("Redis中暂无图书分类数据");
            }

            if (bookTypesJson.startsWith("[")) {
                syncBookTypesToRedis();
                bookTypesJson = stringRedisTemplate.opsForValue().get(BOOK_TYPE_KEY);
            }
            
            BookTypeTreeVO bookTypeTreeVO = objectMapper.readValue(bookTypesJson, BookTypeTreeVO.class);
            
            return Result.success(bookTypeTreeVO);
        } catch (Exception e) {
            log.error("从Redis获取图书分类时发生错误", e);
            try {
                syncBookTypesToRedis();
                String bookTypesJson = stringRedisTemplate.opsForValue().get(BOOK_TYPE_KEY);
                if (bookTypesJson != null) {

                    if (bookTypesJson.startsWith("[")) {

                        return Result.error("Redis中数据格式异常，请检查数据");
                    }
                    BookTypeTreeVO bookTypeTreeVO = objectMapper.readValue(bookTypesJson, BookTypeTreeVO.class);
                    return Result.success(bookTypeTreeVO);
                }
            } catch (Exception syncException) {
                log.error("重新同步图书分类到Redis时发生错误", syncException);
            }
            return Result.error("获取失败: " + e.getMessage());
        }
    }
    
    @Override
    public Result addBookType(BookType bookType) {
        try {
            if (bookType.getIsDelete() == null) {
                bookType.setIsDelete(0);
            }

            int rows = bookTypeMapper.insert(bookType);
            
            if (rows > 0) {
                syncBookTypesToRedis();
                log.info("成功新增图书分类，ID: {}", bookType.getId());
                return Result.success("新增图书分类成功");
            } else {
                return Result.error("新增图书分类失败");
            }
        } catch (Exception e) {
            log.error("新增图书分类时发生错误", e);
            return Result.error("新增失败: " + e.getMessage());
        }
    }
    
    @Override
    public Result updateBookType(BookType bookType) {
        try {
            // 检查要更新的分类是否存在
            BookType existingBookType = bookTypeMapper.findById(bookType.getId());
            if (existingBookType == null) {
                return Result.error("要更新的图书分类不存在");
            }
            
            // 执行更新操作
            int rows = bookTypeMapper.update(bookType);
            
            if (rows > 0) {
                // 更新成功，同步更新Redis中的数据
                syncBookTypesToRedis();
                log.info("成功更新图书分类，ID: {}", bookType.getId());
                return Result.success("更新图书分类成功");
            } else {
                return Result.error("更新图书分类失败");
            }
        } catch (Exception e) {
            log.error("更新图书分类时发生错误", e);
            return Result.error("更新失败: " + e.getMessage());
        }
    }
    
    @Override
    public Result getBookTypeTree() {
        try {
            String bookTypesJson = stringRedisTemplate.opsForValue().get(BOOK_TYPE_KEY);
            
            BookTypeTreeVO bookTypeTreeVO;
            if (bookTypesJson == null) {

                syncBookTypesToRedis();
                bookTypesJson = stringRedisTemplate.opsForValue().get(BOOK_TYPE_KEY);
            }
            

            if (bookTypesJson.startsWith("[")) {

                syncBookTypesToRedis();
                bookTypesJson = stringRedisTemplate.opsForValue().get(BOOK_TYPE_KEY);
            }

            bookTypeTreeVO = objectMapper.readValue(bookTypesJson, BookTypeTreeVO.class);
            return Result.success(bookTypeTreeVO);
        } catch (Exception e) {
            log.error("获取图书分类树时发生错误", e);
            return Result.error("获取失败: " + e.getMessage());
        }
    }
    
    @Override
    public Result deleteBookType(Integer id) {
        try {

            int rows = bookTypeMapper.softDeleteById(id);
            
            if (rows > 0) {

                syncBookTypesToRedis();
                log.info("成功删除图书分类，ID: {}", id);
                return Result.success("删除图书分类成功");
            } else {
                return Result.error("删除图书分类失败");
            }
        } catch (Exception e) {
            log.error("删除图书分类时发生错误", e);
            return Result.error("删除失败: " + e.getMessage());
        }
    }
    

    private List<BookType> buildBookTypeTree(List<BookType> bookTypes) {
        // 获取根节点（parent_id为null或0的节点）
        List<BookType> rootNodes = bookTypes.stream()
                .filter(type -> type.getParentId() == null || type.getParentId() == 0)
                .collect(Collectors.toList());
        
        // 为每个根节点构建子树
        for (BookType rootNode : rootNodes) {
            buildChildTree(rootNode, bookTypes);
            // 设置层级和是否为叶子节点
            rootNode.setLevel(1);
            rootNode.setLeaf(rootNode.getChildren() == null || rootNode.getChildren().isEmpty());
        }
        
        return rootNodes;
    }
    
    /*
     * 递归构建子节点树形结构
     **/
    private void buildChildTree(BookType parent, List<BookType> bookTypes) {
        List<BookType> childNodes = bookTypes.stream()
                .filter(type -> type.getParentId() != null && type.getParentId().equals(parent.getId()))
                .collect(Collectors.toList());
        
        if (!childNodes.isEmpty()) {
            parent.setChildren(childNodes);
            for (BookType childNode : childNodes) {
                childNode.setLevel(parent.getLevel() != null ? parent.getLevel() + 1 : 2);
                buildChildTree(childNode, bookTypes);
                childNode.setLeaf(childNode.getChildren() == null || childNode.getChildren().isEmpty());
            }
        }
    }
}